#pragma once

#include <deque>
#include <mutex>
#include <thread>

#include "common.hpp"
#include "protocol.h"
#include "semaphore.hpp"
#include "serial.hpp"
#include "usb.hpp"
#include "verify.hpp"

class Chassic {
 private:
  Serial serial_;
  bool thread_continue = false;
  std::thread thread_recv_, thread_trans_;
  Protocol_UpData_t mcu_;
#ifdef WHEEL_TEC
  std::deque<Protocol_DownPackage_t> commandq_;
#else
  std::deque<Protocol_DownData_t> commandq_;
#endif

  std::mutex mutex_command_, mutex_mcu_;
  component::Semaphore pack_signal_;

  void ThreadRecv();
  void ThreadTrans();

 public:
  Chassic();
  Chassic(const std::string &dev_path);
  ~Chassic();

  void Init(const std::string &dev_path = "empty");
  void Pack(component::Velocity velocity);

  Protocol_UpData_t GetMCU();
  float GetAverMotor() const;
};

class Android {
 private:
  Serial serial_;
  bool thread_continue = false;
  std::thread thread_recv_, thread_trans_;

  // Andr -> Ai
  component::Velocity vel_;

  // Ai -> Andr
  std::deque<std::vector<uint8_t>> lidars_;
  // std::deque<Protocol_UpData_t> mcus_;

  // std::mutex mutex_mcu_, mutex_andr_,
  std::mutex mutex_lidar_;
  component::Semaphore pack_signal_;

  // void ThreadRecv();
  void ThreadTrans();

 public:
  Android();
  Android(const std::string &dev_path);
  ~Android();

  // component::Velocity GetVel();

  void Init(const std::string &dev_path = "empty");
  // void Pack(Protocol_UpData_t data);
  void Pack(std::vector<uint8_t> data);
};
